﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.DynamicProxy;
using System.Reflection;
using Castle.Core.Interceptor;

namespace EasyProp
{
    public class EasyPropBuilder
    {
        public static bool CanBuild<T>()
        {
            return CanBuild(typeof(T));
        }

        public static bool CanBuild(Type typeToBuild)
        {
            object[] beforeAttributes;
            object[] afterAttributes;
            GetEasyPropClassAttributes(typeToBuild, out beforeAttributes, out afterAttributes);
            return beforeAttributes.Length > 0 || afterAttributes.Length > 0;
        }

        public T Build<T>(params object[] args) where T : class
        {
            return (T)Build(typeof(T), args);
        }

        public object Build(Type typeToBuild, params object[] args)
        {
            PropertySetInterceptor propertySetInterceptor = CreateInterceptor(typeToBuild);
            return _proxyGenerator.CreateClassProxy(typeToBuild, new IInterceptor[]{ propertySetInterceptor}, args);
        }

        private static PropertySetInterceptor CreateInterceptor(Type typeToIntercept)
        {
            PropertySetInterceptor interceptor = new PropertySetInterceptor();

            object[] beforeAttributes;
            object[] afterAttributes;
            GetEasyPropClassAttributes(typeToIntercept, out beforeAttributes, out afterAttributes);

            foreach (PropertySetFilterAttributeBase attribute in beforeAttributes.Concat(afterAttributes))
            {
                foreach (Type commandType in attribute.FilterTypes)
                {
                    IPropertySetterFilter filter = Activator.CreateInstance(commandType) as IPropertySetterFilter;
                    if (attribute is BeforePropertySetFilterAttribute)
                    {
                        interceptor.AddBeforeFilter(filter);
                    }
                    else
                    {
                        if (attribute is AfterPropertySetFilterAttribute)
                        {
                            interceptor.AddAfterFilter(filter);
                        }
                    }
                }
            }

            return interceptor;

        }

        private static void GetEasyPropClassAttributes(Type typeToIntercept, out object[] beforeAttributes, out object[] afterAttributes)
        {
            beforeAttributes = typeToIntercept.GetCustomAttributes(typeof(BeforePropertySetFilterAttribute), true);
            afterAttributes = typeToIntercept.GetCustomAttributes(typeof(AfterPropertySetFilterAttribute), true);
        }

        ProxyGenerator _proxyGenerator = new ProxyGenerator();

    }
}
